home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 20
/
Cream of the Crop 20 (Terry Blount) (1996).iso
/
os2
/
bind493a.zip
/
named
/
ns_forw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-22
|
28KB
|
993 lines
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_forw.c 4.32 (Berkeley) 3/3/91";
static char rcsid[] = "$Id: ns_forw.c,v 8.9 1995/12/22 10:20:30 vixie Exp $";
#endif /* not lint */
/*
* ++Copyright++ 1986
* -
* Copyright (c) 1986
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <syslog.h>
#include <resolv.h>
#include <stdio.h>
#include <errno.h>
#include "named.h"
/*
* Forward the query to get the answer since its not in the database.
* Returns FW_OK if a request struct is allocated and the query sent.
* Returns FW_DUP if this is a duplicate of a pending request.
* Returns FW_NOSERVER if there were no addresses for the nameservers.
* Returns FW_SERVFAIL on malloc error or if asked to do something
* dangerous, such as fwd to ourselves or fwd to the host that asked us.
*
* (no action is taken on errors and qpp is not filled in.)
*/
int
ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
struct databuf *nsp[];
u_char *msg;
int msglen;
struct sockaddr_in *fp;
struct qstream *qsp;
int dfd;
struct qinfo **qpp;
char *dname;
struct namebuf *np;
{
register struct qinfo *qp;
struct sockaddr_in *nsa;
HEADER *hp;
u_int16_t id;
int n;
dprintf(3, (ddt, "ns_forw()\n"));
hp = (HEADER *) msg;
id = hp->id;
/* Look at them all */
for (qp = nsqhead; qp != QINFO_NULL; qp = qp->q_link) {
if (qp->q_id == id &&
bcmp((char *)&qp->q_from, fp, sizeof(qp->q_from)) == 0 &&
((qp->q_cmsglen == 0 && qp->q_msglen == msglen &&
bcmp((char *)qp->q_msg+2, msg+2, msglen-2) == 0) ||
(qp->q_cmsglen == msglen &&
bcmp((char *)qp->q_cmsg+2, msg+2, msglen-2) == 0))) {
dprintf(3, (ddt,
"forw: dropped DUP id=%d\n", ntohs(id)));
nameserIncr(fp->sin_addr, nssRcvdDupQ);
return (FW_DUP);
}
}
qp = qnew();
#if defined(LAME_DELEGATION) || defined(VALIDATE)
getname(np, qp->q_domain, sizeof qp->q_domain);
#endif
qp->q_from = *fp; /* nslookup wants to know this */
if ((n = nslookup(nsp, qp, dname, "ns_forw")) < 0) {
dprintf(2, (ddt, "forw: nslookup reports danger\n"));
qfree(qp);
return (FW_SERVFAIL);
} else if (n == 0 && !fwdtab) {
dprintf(2, (ddt, "forw: no nameservers found\n"));
qfree(qp);
return (FW_NOSERVER);
}
qp->q_stream = qsp;
qp->q_curaddr = 0;
qp->q_fwd = fwdtab;
qp->q_dfd = dfd;
qp->q_id = id;
qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
hp->id = qp->q_nsid = htons(nsid_next());
hp->ancount = htons(0);
hp->nscount = htons(0);
hp->arcount = htons(0);
if ((qp->q_msg = (u_char *)malloc((unsigned)msglen)) == NULL) {
syslog(LOG_NOTICE, "forw: malloc: %m");
qfree(qp);
return (FW_SERVFAIL);
}
bcopy(msg, qp->q_msg, qp->q_msglen = msglen);
if (!qp->q_fwd) {
hp->rd = 0;
qp->q_addr[0].stime = tt;
}
#ifdef SLAVE_FORWARD
if (forward_only)
schedretry(qp, (time_t)slave_retry);
else
#endif /* SLAVE_FORWARD */
schedretry(qp, qp->q_fwd ?(2*RETRYBASE) :retrytime(qp));
nsa = Q_NEXTADDR(qp, 0);
dprintf(1, (ddt,
"forw: forw -> [%s].%d ds=%d nsid=%d id=%d %dms retry %dsec\n",
inet_ntoa(nsa->sin_addr),
ntohs(nsa->sin_port), ds,
ntohs(qp->q_nsid), ntohs(qp->q_id),
(qp->q_addr[0].nsdata != NULL)
? qp->q_addr[0].nsdata->d_nstime
: -1,
(int)(qp->q_time - tt.tv_sec)));
#ifdef DEBUG
if (debug >= 10)
fp_nquery(msg, msglen, ddt);
#endif
if (sendto(ds, (char *)msg, msglen, 0, (struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
syslog(LOG_INFO, "ns_forw: sendto([%s].%d): %m",
inet_ntoa(nsa->sin_addr), ntohs(nsa->sin_port));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
nameserIncr(fp->sin_addr, nssRcvdFwdQ);
nameserIncr(nsa->sin_addr, nssSentFwdQ);
if (qpp)
*qpp = qp;
hp->rd = 1;
return (0);
}
/* struct qdatagram *
* aIsUs(addr)
* scan the datagramq (our list of interface addresses) for "addr"
* returns:
* pointer to qdatagram entry or NULL if no match is found
* notes:
* INADDR_ANY ([0.0.0.0]) is on the datagramq, so it's considered "us"
* author:
* Paul Vixie (DECWRL) April 1991
*/
struct qdatagram *
aIsUs(addr)
struct in_addr addr;
{
struct qdatagram *dqp;
for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next) {
if (addr.s_addr == dqp->dq_addr.s_addr) {
return dqp;
}
}
return NULL;
}
/* haveComplained(tag1, tag2)
* check to see if we have complained about (tag1,tag2) recently
* (note that these are declared as pointers but are never deref'd)
* returns:
* boolean: have we complained recently?
* side-effects:
* outdated complaint records removed from our static list
* author:
* Paul Vixie (DECWRL) April 1991
*/
int
haveComplained(tag1, tag2)
const char *tag1, *tag2;
{
struct complaint {
const char *tag1, *tag2;
time_t expire;
struct complaint *next;
};
static struct complaint *List = NULL;
struct complaint *cur, *next, *prev;
int r = 0;
for (cur = List, prev = NULL; cur; prev = cur, cur = next) {
next = cur->next;
if (tt.tv_sec > cur->expire) {
if (prev)
prev->next = next;
else
List = next;
free((char*) cur);
cur = prev;
} else if ((tag1 == cur->tag1) && (tag2 == cur->tag2)) {
r++;
}
}
if (!r) {
cur = (struct complaint *)malloc(sizeof(stru